package lion.framework.core.conf.loader;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import lion.dev.lang.MapJ;
import lion.framework.core.conf.Config;
import lion.framework.core.conf.IConfigLoader;
import lion.framework.core.conf.anno.ConfigLoader;

/**
 * this config loader read the .ini file to a map every section is a
 * mapJ,section name is the key. <br/>
 * the file path must under classpath <br/>
 *
 * <pre>
 * time   2013 2013年12月11日 下午4:18:27
 * mail   e606@qq.com
 * </pre>
 *
 * @author green
 */
@ConfigLoader("ini")
public class INIConfigLoader implements IConfigLoader {

	private String path;

	public INIConfigLoader(MapJ param) {

		this(param.getString("file"));
	}

	public INIConfigLoader(String path) {

		this.path = path;
	}

	@Override
	public Map<String, Object> load() throws Exception {

		Map<String, Object> result = new HashMap<>();

		String content = null;
		try {
			content = IOUtils.toString(this.getClass().getClassLoader().getResourceAsStream(path));
		} catch (Exception e) {
			throw e;
		}
		if (StringUtils.isBlank(content)) { return result; }

		StringReader sr = new StringReader(content);
		BufferedReader reader = new BufferedReader(sr);

		Map<String, MapJ> sectionsMap = new HashMap<>();
		MapJ itemsMap = new MapJ();
		String currentSection = null;
		String line = null;

		while ((line = reader.readLine()) != null) {
			if (StringUtils.isBlank(line) || line.startsWith("#")) {
				continue;
			}
			if (line.startsWith("[") && line.endsWith("]")) {
				if (itemsMap.size() > 0 && StringUtils.isNotBlank(currentSection)) {
					sectionsMap.put(currentSection, itemsMap);
				}
				currentSection = line.substring(1, line.length() - 1).trim();
				itemsMap = new MapJ();
			} else {
				if (StringUtils.isBlank(currentSection)) {
					continue;
				}
				int index = line.indexOf("=");
				if (index != -1) {
					String key = line.substring(0, index).trim();
					String value = line.substring(index + 1, line.length()).trim();
					itemsMap.put(key, value);
				}
			}
		}

		if (itemsMap.size() > 0 && StringUtils.isNotBlank(currentSection)) {
			sectionsMap.put(currentSection, itemsMap);
		}

		for (String key : sectionsMap.keySet()) {
			MapJ sub = sectionsMap.get(key);
			result.put(key, sub);
			for (String subKey : sub.keySet()) {
				result.put(key + "." + subKey, sub.get(subKey));
			}
		}

		return result;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void save(Config conf) throws Exception {

		List<String> lines = new ArrayList<>();

		for (String key : conf.keySet()) {
			if (key.indexOf(".") == -1) {
				lines.add("[" + key + "]");
				Object o = conf.get(key);
				if (!(o instanceof HashMap)) {
					continue;
				}
				HashMap<String, String> subMap = (HashMap<String, String>) conf.get(key);
				for (String subKey : subMap.keySet()) {
					lines.add(subKey + "=" + subMap.get(subKey));
				}
			}
		}

		FileUtils.writeLines(
				new File(
						URLDecoder.decode(INIConfigLoader.class.getClassLoader().getResource(path).getPath(), "UTF-8")),
				"UTF-8", lines, false);
	}

	@Override
	public <T> T select(String arg) {

		throw new RuntimeException("operation not support in ini config loader");
	}
}
